/*


    example-gpios {
        compatible = "example,gpio";
        gpios = <
				&gpio4 16 1  // a
				&gpio4 26 1  // b
				&gpio4 25 1  // c  
				&gpio4 27 1  // d
				&gpio4 28 1  // e
				&gpio4 14 1  // f
				&gpio1 27 1  // g
				
				&gpio1 26 1  // bit0
				&gpio3 25 1  // bit1
				&gpio3 26 1  // bit2
		>;
    };

该驱动必须将ＬＩＮＵＸ的ｔｉｃｋ周期改成１ｍｓ否则数码管显示有残影

-> Kernel Features
- -> Timer frequency (<choice> [=y])  

CONFIG_HZ_1000=y
CONFIG_HZ=1000
*/
#include <linux/module.h>
#include <linux/of_gpio.h>
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/kthread.h>

int flag = 0;
#define NUM_GPIOS 10

#define I_SEG_A 0
#define I_SEG_B 1
#define I_SEG_C 2
#define I_SEG_D 3
#define I_SEG_E 4
#define I_SEG_F 5
#define I_SEG_G 6

#define BIT_0 7
#define BIT_1 8
#define BIT_2 9


#define EN_BIT (0)

#define SEG_A  0b00000001
#define SEG_B  0b00000010
#define SEG_C  0b00000100
#define SEG_D  0b00001000
#define SEG_E  0b00010000
#define SEG_F  0b00100000
#define SEG_G  0b01000000

#define CNT_BATTERY (1)

static int gpios[NUM_GPIOS];
static struct timer_list example_timer_0;
static struct timer_list example_timer_1;
static struct timer_list example_timer_2;
static int current_gpio = 0;

const unsigned char segments[] = {
    SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F,             // 0
    SEG_B | SEG_C,                                             // 1
    SEG_A | SEG_B | SEG_D | SEG_E | SEG_G,                     // 2
    SEG_A | SEG_B | SEG_C | SEG_D | SEG_G,                     // 3
    SEG_B | SEG_C | SEG_F | SEG_G,                             // 4
    SEG_A | SEG_C | SEG_D | SEG_F | SEG_G,                     // 5
    SEG_A | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G,             // 6
    SEG_A | SEG_B | SEG_C,                                     // 7
    SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G,     // 8
    SEG_A | SEG_B | SEG_C | SEG_D | SEG_F | SEG_G,             // 9
    0,                                                         // NULL  没有任何显示
};


const unsigned char letters[] = {
    SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G,             // A
    SEG_C | SEG_D | SEG_E | SEG_F | SEG_G,                     // B
    SEG_A | SEG_D | SEG_E | SEG_F,                             // C
    SEG_B | SEG_C | SEG_D | SEG_E | SEG_G,                     // D
    SEG_A | SEG_D | SEG_E | SEG_F | SEG_G,                     // E
    SEG_A | SEG_E | SEG_F | SEG_G,                             // F
    SEG_A | SEG_C | SEG_E | SEG_F | SEG_G,                     // G
    SEG_B | SEG_C | SEG_E | SEG_F | SEG_G,                     // H
    SEG_B | SEG_C,                                             // I
    SEG_A | SEG_B | SEG_C | SEG_D,                             // J
    SEG_D | SEG_E | SEG_F,                                     // K
    SEG_D | SEG_E | SEG_F | SEG_G,                             // L
    SEG_A | SEG_C | SEG_E | SEG_G,                             // M
    SEG_C | SEG_E | SEG_G,                                     // N
    SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F,             // O
    SEG_A | SEG_B | SEG_E | SEG_F | SEG_G,                     // P
    SEG_A | SEG_B | SEG_C | SEG_F | SEG_G,                     // Q
    SEG_E | SEG_G,                                             // R
    SEG_A | SEG_C | SEG_D | SEG_F | SEG_G,                     // S
    SEG_D | SEG_E | SEG_F | SEG_G,                             // T
    SEG_C | SEG_D | SEG_E,                                     // U
    SEG_B | SEG_C | SEG_D | SEG_E | SEG_F,                     // V
    SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G,             // W
    SEG_B | SEG_C | SEG_E | SEG_F | SEG_G,                     // X
    SEG_B | SEG_C | SEG_D | SEG_F | SEG_G,                     // Y
    SEG_A | SEG_B | SEG_D | SEG_E | SEG_G,                     // Z
    0,                                                         // NULL  没有任何显示
};



void show_letters(int value) {
    if (value > sizeof(letters)) {
        value = sizeof(letters)-1;
    }
    // gpio_set_value(gpios[I_SEG_A], 1);
    // gpio_set_value(gpios[I_SEG_B], 1);
    // gpio_set_value(gpios[I_SEG_C], 1);
    // gpio_set_value(gpios[I_SEG_D], 1);
    // gpio_set_value(gpios[I_SEG_E], 1);
    // gpio_set_value(gpios[I_SEG_F], 1);
    // gpio_set_value(gpios[I_SEG_G], 1);

    // gpio_set_value(gpios[I_SEG_B], 0);

    // tick = value;
    if (letters[value] & SEG_A) {
        gpio_set_value(gpios[I_SEG_A], 0);
    }
    else {
        gpio_set_value(gpios[I_SEG_A], 1);
    }
    if (letters[value] & SEG_B) {
        gpio_set_value(gpios[I_SEG_B], 0);
    }
    else {
        gpio_set_value(gpios[I_SEG_B], 1);
    }
    if (letters[value] & SEG_C) {
        gpio_set_value(gpios[I_SEG_C], 0);
    }
    else {
        gpio_set_value(gpios[I_SEG_C], 1);
    }
    if (letters[value] & SEG_D) {
        gpio_set_value(gpios[I_SEG_D], 0);
    }
    else {
        gpio_set_value(gpios[I_SEG_D], 1);
    }
    if (letters[value] & SEG_E) {
        gpio_set_value(gpios[I_SEG_E], 0);
    }
    else {
        gpio_set_value(gpios[I_SEG_E], 1);
    }
    if (letters[value] & SEG_F) {
        gpio_set_value(gpios[I_SEG_F], 0);
    }
    else {
        gpio_set_value(gpios[I_SEG_F], 1);
    }
    if (letters[value] & SEG_G) {
        gpio_set_value(gpios[I_SEG_G], 0);
    }
    else {
        gpio_set_value(gpios[I_SEG_G], 1);
    }


    // for ()

    /* 更新当前GPIO索引 */
    // current_gpio = (current_gpio + 1) % NUM_GPIOS;
    // printk("led \r\n");
    /* 重启定时器 */
    
    
}

void show_value(int value) {
    // 下面的判断无所谓，因为数据来源于sn_int，肯定在0-9之间
    // if (value > sizeof(segments)) {
    //     value = sizeof(segments)-1;
    // }
    // tick = value;
    if (segments[value] & SEG_A) {
        gpio_set_value(gpios[I_SEG_A], 0);
    }
    else {
        gpio_set_value(gpios[I_SEG_A], 1);
    }
    if (segments[value] & SEG_B) {
        gpio_set_value(gpios[I_SEG_B], 0);
    }
    else {
        gpio_set_value(gpios[I_SEG_B], 1);
    }
    if (segments[value] & SEG_C) {
        gpio_set_value(gpios[I_SEG_C], 0);
    }
    else {
        gpio_set_value(gpios[I_SEG_C], 1);
    }
    if (segments[value] & SEG_D) {
        gpio_set_value(gpios[I_SEG_D], 0);
    }
    else {
        gpio_set_value(gpios[I_SEG_D], 1);
    }
    if (segments[value] & SEG_E) {
        gpio_set_value(gpios[I_SEG_E], 0);
    }
    else {
        gpio_set_value(gpios[I_SEG_E], 1);
    }
    if (segments[value] & SEG_F) {
        gpio_set_value(gpios[I_SEG_F], 0);
    }
    else {
        gpio_set_value(gpios[I_SEG_F], 1);
    }
    if (segments[value] & SEG_G) {
        gpio_set_value(gpios[I_SEG_G], 0);
    }
    else {
        gpio_set_value(gpios[I_SEG_G], 1);
    }

    /* 更新当前GPIO索引 */
    // current_gpio = (current_gpio + 1) % NUM_GPIOS;
    // printk("led \r\n");
    /* 重启定时器 */
}

int g_tick = 0;
static void example_timer_callback_0(struct timer_list *t)
{
    int i;
    static int state = 0;
    /* 切换GPIO电平 */
    for (i = 0; i < NUM_GPIOS; i++) {
        // gpio_set_value(gpios[i], i == current_gpio ? 1 : 0);
        // state = gpio_get_value(gpios[i]);
        // printk("stat %d %d\r\n", i, state);
        // gpio_set_value(gpios[i], !state);
    }
    
    // state = gpio_get_value(gpios[0]);
    
    state = !state;
    // printk("stat %d %d\r\n", 0, g_tick);
    // g_tick = 0;
    if (++g_tick > 8)  {
        g_tick = 0;
    }
    i = 10000;
    // while (i--) {
    //     gpio_set_value(gpios[BIT_0], 1);
    //     gpio_set_value(gpios[BIT_1], 0);
    //     gpio_set_value(gpios[BIT_2], 0);
    //     show_value(5);
    //     msleep(1);
    //     gpio_set_value(gpios[BIT_0], 0);
    //     gpio_set_value(gpios[BIT_1], 1);
    //     gpio_set_value(gpios[BIT_2], 0);
    //     show_value(1);
    //     msleep(1);
    // }

    mod_timer(&example_timer_0, jiffies + msecs_to_jiffies(1000));
}

static void example_timer_callback_2(struct timer_list *t)
{
    int i;
    static int state = 0;
    /* 切换GPIO电平 */
    for (i = 0; i < NUM_GPIOS; i++) {
        // gpio_set_value(gpios[i], i == current_gpio ? 1 : 0);
        // state = gpio_get_value(gpios[i]);
        // printk("stat %d %d\r\n", i, state);
        // gpio_set_value(gpios[i], !state);
    }
    
    // state = gpio_get_value(gpios[0]);
    
    state = !state;
    // printk("stat %d %d\r\n", 0, state);
    static int tick = 0;
    if (++tick > 8)  {
        tick = 0;
    }
    gpio_direction_output(gpios[BIT_0], 0);
    gpio_direction_output(gpios[BIT_1], 1);
    gpio_direction_output(gpios[BIT_2], 0);
    show_value(2);
    mod_timer(&example_timer_2, jiffies + msecs_to_jiffies(2));
}
#if 0
static ssize_t sn_show(
    struct device *dev,
    struct device_attribute *attr,
    char *buf)
{
	struct misc_batt_data *pdata = (struct misc_batt_data *)dev->platform_data;

	return snprintf(buf, PAGE_SIZE, "%s\n", "asdf");
}
static ssize_t sn_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
    // 在这里处理对 /sys/class/misc/product/sn 的写入
    // buf 包含写入的数据, count 是数据的长度
    printk("Received serial number: %.*s\n", (int)count, buf);
    return count;
}



// static DEVICE_ATTR(
//     config, S_IRUGO, config_show, NULL);
static DEVICE_ATTR(
    sn, S_IRUGO, sn_show, sn_store);
// static DEVICE_ATTR(
//     board, S_IRUGO, board_show, NULL);
// static DEVICE_ATTR(
//     boot_sha1, S_IRUGO, boot_sha1_show, NULL);
// static DEVICE_ATTR(
//     boot_build, S_IRUGO, boot_build_show, NULL);
#endif
static struct miscdevice *pmisc;
struct product_data
{
	// char *board;
	struct miscdevice     *pmisc;
};

void fun_init(struct platform_device *pdev)
{
	int                    i;
	char                   name[16];
	struct device         *this_dev;
	struct miscdevice     *tpmisc;
	// struct misc_batt_data *pdata, *tpdata;
	struct product_data  *pdata;

	pdata = platform_get_drvdata(pdev);
	pdata->pmisc = devm_kzalloc(&pdev->dev, sizeof(struct miscdevice) * CNT_BATTERY, GFP_KERNEL);
	
	// pmisc = kzalloc(sizeof(struct miscdevice) * CNT_BATTERY, GFP_KERNEL);
	// pdata = kzalloc(sizeof(struct misc_batt_data) * CNT_BATTERY, GFP_KERNEL);

	tpmisc = pdata->pmisc;
	snprintf(name, sizeof(name), "led-dig");
	tpmisc->name  = name;
	tpmisc->minor = MISC_DYNAMIC_MINOR;
	tpmisc->fops  = NULL;
	misc_register(tpmisc);

	this_dev                = tpmisc->this_device;
	// this_dev = &pdev->dev;
	
	// this_dev->platform_data = tpdata;


	// strncpy(tpdata->name, name, sizeof(((struct misc_batt_data *)(0))->name));

	// device_create_file(this_dev, &dev_attr_config);
	// device_create_file(this_dev, &dev_attr_sn);
	// device_create_file(this_dev, &dev_attr_board);
	// device_create_file(this_dev, &dev_attr_boot_sha1);
	// device_create_file(this_dev, &dev_attr_boot_build);
}


static char sn_value[20] = "1234567890";
static int sn_int = 0;
static ssize_t sn_show(struct device *dev, struct device_attribute *attr, char *buf)
{
    return sprintf(buf, "%s\n", sn_value);
}

static ssize_t sn_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
    // size_t len = min_t(size_t, count, sizeof(sn_value) - 1);
    // memcpy(sn_value, buf, len);
    // sn_value[len] = '\0';

    // return count;
    size_t len = min_t(size_t, count, sizeof(sn_value) - 1);
    memcpy(sn_value, buf, len);
    sn_value[len] = '\0';

    sscanf(sn_value, "%d", &sn_int);
    printk("sdf %d\r\n", sn_int);
    // show_value(sn_int);
    flag = 0;
    return count;
}

static DEVICE_ATTR_RW(sn);

static char letter_value[20] = "1234567890";

static ssize_t letter_show(struct device *dev, struct device_attribute *attr, char *buf)
{
    return sprintf(buf, "%s\n", letter_value);
}

static ssize_t letter_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
    // size_t len = min_t(size_t, count, sizeof(letter_value) - 1);
    // memcpy(letter_value, buf, len);
    // letter_value[len] = '\0';

    // return count;
    size_t len = min_t(size_t, count, sizeof(letter_value) - 1);
    memcpy(letter_value, buf, len);
    letter_value[len] = '\0';
    // printk(KERN_INFO "Converted string '%s' to integer:\n", letter_value);
    // int sn_int;
    // if (sscanf(letter_value, "%d", &sn_int) == 1) {
    //     // 成功将字符串转换为整数
    //     printk(KERN_INFO "Converted string '%s' to integer: %d\n", sn_value, sn_int);
    // } else {
    //     // 转换失败
    //     printk(KERN_ERR "Failed to convert string '%s' to integer\n", sn_value);
    // }
    // show_value(sn_int);
    flag = 1;
    return count;
}
static DEVICE_ATTR_RW(letter);

static struct attribute *example_attrs[] = {
    &dev_attr_sn.attr,
    &dev_attr_letter.attr,
    NULL,
};

static const struct attribute_group example_attr_group = {
    .attrs = example_attrs,
};
void delay(int d)
{
    volatile int i;
    for (i = 0;i < 1000*d; i++) {

    }
}
static struct task_struct *my_thread;
static struct task_struct *my_thread_letter;

int my_thread_func(void *data)
{
    int i, sn;

    gpio_set_value(gpios[BIT_0], EN_BIT);
    gpio_set_value(gpios[BIT_1], !EN_BIT);
    gpio_set_value(gpios[BIT_2], !EN_BIT);
    while (!kthread_should_stop()) {
        if (flag != 0) {
            msleep(100);
            // printk("ss\r\n");
            continue;
        }
        // printk("whil\r\n");
        
        // 在这里编写内核线程的逻辑
        // printk(KERN_INFO "Hello from kernel thread!\n");
        sn = sn_int;
        // printk("sn %d\r\n", sn);
        // show_value(g_tick+2);
        show_value(sn % 10);
        // printk("sn %d\r\n", sn % 10);
        gpio_set_value(gpios[BIT_0], EN_BIT);
        gpio_set_value(gpios[BIT_1], !EN_BIT);
        gpio_set_value(gpios[BIT_2], !EN_BIT);
        msleep(5);
        
        sn = sn / 10;
        
        // show_value(g_tick+1);
        show_value(sn % 10);
        // printk("sn %d\r\n", sn % 10);
        gpio_set_value(gpios[BIT_0], !EN_BIT);
        gpio_set_value(gpios[BIT_1], EN_BIT);
        gpio_set_value(gpios[BIT_2], !EN_BIT);
        msleep(5);
        
        sn = sn / 10;
        // show_value(g_tick);
        show_value(sn % 10);
        gpio_set_value(gpios[BIT_0], !EN_BIT);
        gpio_set_value(gpios[BIT_1], !EN_BIT);
        gpio_set_value(gpios[BIT_2], EN_BIT);    
        msleep(5);
    }

    return 0;
}

int my_letter_func(void *data)
{
    int i, sn;

    gpio_set_value(gpios[BIT_0], EN_BIT);
    gpio_set_value(gpios[BIT_1], !EN_BIT);
    gpio_set_value(gpios[BIT_2], !EN_BIT);
    while (!kthread_should_stop()) {
        if (flag != 1) {
            msleep(0);
            continue;
        }
        // 在这里编写内核线程的逻辑
        // printk(KERN_INFO "Hello from kernel thread!\n");
        sn = sn_int;
        
        // show_value(g_tick+2);
        show_letters(letter_value[0] - 'a');
        // printk("sn %d\r\n", sn % 10);
        gpio_set_value(gpios[BIT_0], !EN_BIT);
        gpio_set_value(gpios[BIT_1], !EN_BIT);
        gpio_set_value(gpios[BIT_2], EN_BIT);
        msleep(5);
        
        sn = sn / 10;
        
        // show_letters(letter_value+1);
        show_letters(letter_value[1] - 'a');
        // printk("sn %d\r\n", sn % 10);
        gpio_set_value(gpios[BIT_0], !EN_BIT);
        gpio_set_value(gpios[BIT_1], EN_BIT);
        gpio_set_value(gpios[BIT_2], !EN_BIT);
        msleep(5);
        
        sn = sn / 10;
        // show_letters(letter_value);
        show_letters(letter_value[2] - 'a');
        gpio_set_value(gpios[BIT_0], EN_BIT);
        gpio_set_value(gpios[BIT_1], !EN_BIT);
        gpio_set_value(gpios[BIT_2], !EN_BIT);    
        msleep(5);
    }

    return 0;
}

static int example_probe(struct platform_device *pdev)
{
    int i, ret;
    printk("ssdfasdf\r\n");
    /* 从设备树加载GPIO引脚 */
    for (i = 0; i < NUM_GPIOS; i++) {
        // gpios[i] = of_get_gpio(pdev->dev.of_node, i);
        printk("i %d\r\n", i);
        gpios[i]  = of_get_named_gpio(pdev->dev.of_node, "gpios", i);
        if (gpios[i] < 0) {
            dev_err(&pdev->dev, "Failed to get gpio %d\n", i);
            return gpios[i];
        }
        ret = devm_gpio_request(&pdev->dev, gpios[i], "led-digital");
        if (ret) {
            dev_err(&pdev->dev, "Failed to request gpio %d\n", i);
            return ret;
        }
        gpio_direction_output(gpios[i], 1);
    }
    gpio_set_value(gpios[BIT_0], 1);
    gpio_set_value(gpios[BIT_1], 0);
    gpio_set_value(gpios[BIT_2], 0);
   

    /* 初始化定时器 */
    timer_setup(&example_timer_0, example_timer_callback_0, 0);
    mod_timer(&example_timer_0, jiffies + msecs_to_jiffies(1000));

    // timer_setup(&example_timer_2, example_timer_callback_2, 0);
    // mod_timer(&example_timer_2, jiffies + msecs_to_jiffies(1000));
    // fun_init(pdev);


    struct device *this_dev;
    // int ret;

    this_dev = &pdev->dev;

    ret = sysfs_create_group(&this_dev->kobj, &example_attr_group);
    if (ret) {
        dev_err(this_dev, "Failed to create sysfs attributes\n");
        return ret;
    }



    my_thread = kthread_create(my_thread_func, NULL, "my_thread");
    if (IS_ERR(my_thread)) {
        printk(KERN_ERR "Failed to create kernel thread\n");
        return PTR_ERR(my_thread);
    }

    wake_up_process(my_thread); // 启动内核线程

    my_thread_letter = kthread_create(my_letter_func, NULL, "my_thread_letter");
    if (IS_ERR(my_thread_letter)) {
        printk(KERN_ERR "Failed to create kernel thread\n");
        return PTR_ERR(my_thread_letter);
    }

    wake_up_process(my_thread_letter); // 启动内核线程
    dev_info(this_dev, "Example driver probed\n");
    return 0;
}

void fun_exit(void )
{
		int i;
	struct miscdevice *tpmisc;

	if (pmisc) {
		tpmisc = pmisc;
		for (i = 0; i < CNT_BATTERY; i++) {
			misc_deregister(tpmisc);
			tpmisc++;
		}
		kfree(pmisc);
	}
}

static int example_remove(struct platform_device *pdev)
{
    struct device *this_dev = &pdev->dev;

    sysfs_remove_group(&this_dev->kobj, &example_attr_group);
    int i;

    /* 删除定时器 */
    del_timer_sync(&example_timer_0);
    del_timer_sync(&example_timer_2);

    for (i = 0; i < NUM_GPIOS; i++) {
        gpio_free(gpios[i]);
    }

    if (my_thread) {
        kthread_stop(my_thread); // 停止内核线程
    }
    if (my_thread_letter) {
        kthread_stop(my_thread_letter); // 停止内核线程
    }

    return 0;
}

static const struct of_device_id example_of_match[] = {
    { .compatible = "example,gpio", },
    { /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, example_of_match);

static struct platform_driver example_driver = {
    .probe = example_probe,
    .remove = example_remove,
    .driver = {
        .name = "example-driver",
        .of_match_table = example_of_match,
    },
};
module_platform_driver(example_driver);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Assistant");
MODULE_DESCRIPTION("Example device tree driven GPIO driver with timer");